﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml;
using System.Xml.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Drawing;

namespace SpriteSheetsCreator {
    public class SettingsIO {
        /// <summary>
        /// Save current gui params - used to get application start over with same parameters
        /// </summary>
        public static void loadeGuiParams() {
            if (!File.Exists(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"SpriteSheetsCreator\guiXmlData.xml"))) {
                return;
            }

            // If file exists, load XML saved parameters
            XDocument guiXmlData = XDocument.Load(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"SpriteSheetsCreator\guiXmlData.xml"), LoadOptions.None);

            // Load images from files (restore previous application state)
            try {
                App.ViewModel.ImagesList.Clear();
                loadImagesFromFilenames(guiXmlData.Descendants("openFiles").FirstOrDefault().Descendants("file").OrderBy(f => f.Attribute("id").Value.toInteger()).Select(f => f.Attribute("imageFullPath").Value).ToArray<string>());
            }
            catch (Exception ex) {

            }

            // Restore animation settings
            try {
                App.ViewModel.AutoreverseAnim = guiXmlData.Descendants("animationSettings").FirstOrDefault().Attribute("autoreverse").Value.toBool();
                App.ViewModel.GuiAnimationSpeedStr = guiXmlData.Descendants("animationSettings").FirstOrDefault().Attribute("speed").Value;
            }
            catch (Exception ex) {

            }
        }

        /// <summary>
        /// Save current gui params - used to get application start over with same parameters
        /// </summary>
        public static void saveGuiParams() {
            XDocument guiXmlData = new XDocument();
            guiXmlData.Add(new XElement("guiData"));

            // Save currently open files
            XElement openFilesXmlElt = new XElement("openFiles");
            int i = 0;
            foreach (ImageViewModel image in App.ViewModel.ImagesList) {
                XElement fileXmlElt = new XElement("file");
                fileXmlElt.Add(new XAttribute("id", (i++).ToString()), new XAttribute("imageFullPath", image.ImageFullPath));
                openFilesXmlElt.Add(fileXmlElt);
            }
            guiXmlData.Descendants("guiData").FirstOrDefault().Add(openFilesXmlElt);

            // Save animation settings
            XElement animSettingsXmlElt = new XElement("animationSettings");
            animSettingsXmlElt.Add(new XAttribute("autoreverse", App.ViewModel.AutoreverseAnim.ToString()));
            animSettingsXmlElt.Add(new XAttribute("speed", App.ViewModel.GuiAnimationSpeedStr));
            guiXmlData.Descendants("guiData").FirstOrDefault().Add(animSettingsXmlElt);

            // Save parameters to disk
            if (!Directory.Exists(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"SpriteSheetsCreator"))) {
                Directory.CreateDirectory(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"SpriteSheetsCreator"));
            }
            guiXmlData.Save(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"SpriteSheetsCreator\guiXmlData.xml"));
        }

        /// <summary>
        /// Save sprite sheet into PNG file according to filename parameter
        /// </summary>
        /// <param name="filename"></param>
        public static void saveImageResult(string filename) {
            // Calculate result size
            int pixelResultWidth = 0;
            int pixelResultHeight = 0;
            int maxSourceWidth = App.ViewModel.ImagesList.Max(i => i.ImageBitmap.PixelWidth);
            int maxSourceHeight = App.ViewModel.ImagesList.Max(i => i.ImageBitmap.PixelHeight);
            // Fixed size for sprites
            if (App.ViewModel.FixedSpriteSize) {
                pixelResultWidth = maxSourceWidth * App.ViewModel.ImagesList.Count;
            }
            // Original size for sprites
            else {
                pixelResultWidth = App.ViewModel.ImagesList.Sum(i => i.ImageBitmap.PixelWidth);
                pixelResultHeight = maxSourceHeight;
            }

            // Creates a new empty image with the pre-defined palette
            WriteableBitmap resultBm = BitmapFactory.New(pixelResultWidth, pixelResultHeight);
            resultBm.Clear(Colors.Transparent);

            // Draw sprites on sheet
            int crtXPixelPos = 0;
            foreach (ImageViewModel image in App.ViewModel.ImagesList) {
                // Convert to preserve alpha transparency
                WriteableBitmap sourceImage = BitmapFactory.ConvertToPbgra32Format(image.ImageBitmap);
                // Copy sprite on result sheet Bitmap
                resultBm.Blit(new Rect(crtXPixelPos, 0, sourceImage.PixelWidth, sourceImage.PixelHeight), sourceImage,
                    new Rect(0, 0, sourceImage.PixelWidth, sourceImage.PixelHeight), Colors.White, WriteableBitmapExtensions.BlendMode.Alpha);

                // Fixed size for sprites
                if (App.ViewModel.FixedSpriteSize) {
                    crtXPixelPos += maxSourceWidth;
                }
                // Original size for sprites
                else {
                    crtXPixelPos += sourceImage.PixelWidth;
                }
            }

            FileStream stream = new FileStream(filename, FileMode.Create);
            PngBitmapEncoder encoder = new PngBitmapEncoder();
            encoder.Interlace = PngInterlaceOption.On;
            encoder.Frames.Add(BitmapFrame.Create(resultBm.Clone()));
            encoder.Save(stream);
            stream.Close();
        }

        public static void loadImagesFromFilenames(string[] filenames) {
            foreach (string filename in filenames) {
                if (filename.ToLower().EndsWith("png")) {
                    // Load image stream
                    Stream imageStreamSource = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
                    PngBitmapDecoder decoder = new PngBitmapDecoder(imageStreamSource, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
                    BitmapSource bitmapSource = decoder.Frames[0];

                    // Add image to list box
                    App.ViewModel.ImagesList.Add(new ImageViewModel() { ImageName = filename.subRemoveLeft(filename.LastIndexOf('\\') + 1), ImageFullPath = filename, ImageBitmap = bitmapSource });
                }
            }
        }
    }
}
